/*
 Copyright (c) Whitemice Consulting, 2007, 2008, 2009
 Adam Tauno Williams <awilliam@whitemice.org>
 License: MIT/X11

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/
using System;
using Whitemice.ZOGI;
using Whitemice.ZOGI.GtkWidgets;
using Gtk;

namespace Whitemice.ZOGI.GtkForms
{
  [System.ComponentModel.Category("Forms")]
  [System.ComponentModel.ToolboxItem(true)]
  public partial class TaskDetailForm : Gtk.Bin, IStorableEntityForm, IVerifiedEntityForm
	{
		protected int 									              projectId;
		protected int                                 executantId;
		protected int										              taskId;
		protected Array                               dateChars, numberChars;
	  public EventHandler                           OnProjectChangeClicked;
	  public EventHandler                           OnExecutantChangeClicked;
		
		public TaskDetailForm()
		{
			this.Build();
			dateChars = "1234567890-".ToCharArray();
			numberChars = "1234567890".ToCharArray();
			completed.Sensitive = false;
			InitializeCombos();
			this.ShowAll();
			projectId = 0;
			executantId = 0;
		} // end TaskDetailForm

    public void Verify()
    {
      DateTime?  startDate, endDate;
      try { startDate = Convert.ToDateTime(start.Text.Trim()); }
      catch { throw new Exception("Start date is not a valid date."); }
      try { endDate = Convert.ToDateTime(end.Text.Trim()); }
      catch { throw new Exception("End date is not a valid date,"); }
      if (startDate > endDate)
        throw new Exception("End date is prior to start date.");
      if (Name.Length < 3)
        throw new Exception("Task name is too short.");
    }
		
		public bool Take(Entity _entity)
		{
			Task	task;
			
			if(_entity is Whitemice.ZOGI.Task)
				task = (_entity as Whitemice.ZOGI.Task);
				else throw new Exception("Unexpected entity type passed to form");
		
			task.Name = title.Text ?? string.Empty;
      task.Keywords = keywords.Text ?? string.Empty;
			
			task.Start = Convert.ToDateTime(start.Text);
			task.End = Convert.ToDateTime(end.Text);
			
			task.ActualWork = Convert.ToInt32(actualWork.Text);
			task.TotalWork = Convert.ToInt32(totalWork.Text);
			//task.Miles = Convert.ToInt32(travel.Text);
			task.AccountingInfo = accountingInfo.Text.Trim();
			task.Notification = Notification;
			task.Sensitivity = Sensitivity;
			task.Priority = Priority;
			task.PercentComplete = Percentage;
			task.ProjectId = projectId;
			task.ExecutorId = executantId;
			if (task.ObjectId < 0)
			  task.Comment = comment.Buffer.Text;
      return true;
		} // end Take
		
		public void Fill(Entity _entity)
		{
			Task	task;
			
			if(_entity is Whitemice.ZOGI.Task)
				task = (_entity as Whitemice.ZOGI.Task);
				else throw new Exception("Unexpected entity type passed to form");
		
			taskId = task.ObjectId;
			title.Text = task.Name;
			creator.Text = task.CreatorName ?? string.Empty;
			executant.Text = task.ExecutorName ?? string.Empty;
			accountingInfo.Text = task.AccountingInfo ?? string.Empty;
			associatedContacts.Text = task.AssociatedContacts ?? string.Empty;
			associatedCompanies.Text = task.AssociatedCompanies ?? string.Empty;
			keywords.Text = task.Keywords ?? string.Empty;
			ProjectDescription = task.ProjectName ?? string.Empty;
       executantId = task.ExecutorId;
			actualWork.Text = task.ActualWork.ToString();
			totalWork.Text = task.TotalWork.ToString();
			//travel.Text = task.Miles.ToString();
			Notification = task.Notification;
			Sensitivity = task.Sensitivity;
			Priority = task.Priority;
			Percentage = task.PercentComplete;
			projectId = task.ProjectId;
			ProjectDescription = task.ProjectName ?? string.Empty;
			status.Text = ZOGIUtility.TaskStatusDescription(task.Status);
			// end start
			if (task.Start == DateTime.MinValue)
				start.Text = "";
				else	start.Text = task.Start.ToString("yyyy-MM-dd");
			// end date
			if (task.End == DateTime.MinValue)
				end.Text = "";
				else	end.Text = task.End.ToString("yyyy-MM-dd");
		  // completed date
			if (task.CompletionDate == DateTime.MinValue)
				completed.Text = "n/a";
			else
				completed.Text = task.CompletionDate.ToString();
      if (task.ObjectId < 0)
			{
			  // This is a new task
			  outlookHBox.Hide(); outlookHBox.Visible = false;
			  workHBox.Hide(); workHBox.Visible = false;
			  commentFrame.ShowAll();
			  comment.Buffer.Text = task.Comment;
			} else
			  {
			    // This is a created task; show work & outlook, hide the comment.
			    // Comments on created tasks appear in the annotations tab. */
			    outlookHBox.ShowAll(); 
			    workHBox.ShowAll();			  
			    commentFrame.Hide();
			  }
		} // end Fill
		
		public void Clear()
		{
		} // end Clear

		protected virtual void OnProjectSearchClicked(object sender, System.EventArgs e)
		{
		  OnProjectChangeClicked(sender, e);
		} // end OnChangeProjectClicked
		
		protected virtual void OnExecutantSearchClicked(object sender, System.EventArgs e)
		{
		  OnExecutantChangeClicked(sender, e);
		} // end OnExecutantSearchClicked
		
		protected virtual void OnDateFocusOutEvent(
			object o, 
			Gtk.FocusOutEventArgs args)
		{
			string		entryValue;
			
			entryValue = ((Entry)o).Text;
			try 
			{
				Convert.ToDateTime(entryValue);
			} catch (Exception ex)
				{
					new MessageBox(ex.Message);
					(o as Gtk.Entry).GrabFocus();
				}
		} // DateFocusOutEvent 

		protected virtual void OnWorkActivated (object sender, System.EventArgs e)
		{
		  workHBox.ShowAll();
		} // end OnWorkActivated

		protected virtual void OnOutlookActivated (object sender, System.EventArgs e)
		{
		  outlookHBox.ShowAll();
		} // end OnOutlookActivated
	
		public string ExecutantDescription
		{
		  get { return executant.Text; }
		  set { executant.Text = value; }
		} // end ExecutantDescription
		
		public string ProjectDescription
		{
		  get { return projectName.Text; }
		  set { projectName.Text = value; }
		} // end ProjectDescription
		
		public int ProjectId
		{
		  get { return projectId; }
		  set { projectId = value; }
		}
		
		public int ExecutantId
		{
		  get { return executantId; }
		  set { executantId = value; }
		}
		
		protected void InitializeCombos()
		{
			notification.AppendText("Never");
			notification.AppendText("Accept/Done");
			notification.AppendText("Always");
			notification.Active = 0;
			priority.AppendText("Very High");
			priority.AppendText("High");
			priority.AppendText("Average");
			priority.AppendText("Low");
			priority.AppendText("Very Low");
			priority.Active = 2;
			sensitivity.AppendText("Public");
			sensitivity.AppendText("Personal");
			sensitivity.AppendText("Private");
			sensitivity.AppendText("Confidential");
			sensitivity.Active = 0;
		} // End InitializeCombos

    	[GLib.ConnectBefore]
		protected virtual void OnDateFieldKeyPressEvent (object o, Gtk.KeyPressEventArgs args)
		{
		  if ((Array.IndexOf(dateChars, Convert.ToChar(args.Event.Key)) > -1) ||
		      (args.Event.Key == Gdk.Key.BackSpace) ||
		      (args.Event.Key == Gdk.Key.Tab) ||
		      (args.Event.Key == Gdk.Key.ISO_Left_Tab))
		  {
		    args.RetVal = false;
		    return;
		  }
		  args.RetVal = true;
		} /* end OnDateFieldKeyPressEvent */
		
    [GLib.ConnectBefore]
		protected virtual void OnNumericFieldKeyPressEvent (object o, Gtk.KeyPressEventArgs args)
		{
		  if ((Array.IndexOf(numberChars, Convert.ToChar(args.Event.Key)) > -1) ||
		      (args.Event.Key == Gdk.Key.BackSpace) ||
		      (args.Event.Key == Gdk.Key.Tab) ||
		      (args.Event.Key == Gdk.Key.ISO_Left_Tab))
		  {
		    args.RetVal = false;
		    return;
		  }
		  args.RetVal = true;
		} /* end OnNumericFieldKeyPressEvent */	
	
		public TaskNotification Notification
		{
			get
			{
				switch(notification.Active)
				{
					case 1: return TaskNotification.AcceptDone;
					case 2: return TaskNotification.Always;
					default: return TaskNotification.Never;
				}
			}
			set
			{
				switch(value)
				{
					case TaskNotification.Never: notification.Active = 0; break;
					case TaskNotification.Always: notification.Active = 2; break;
					case TaskNotification.AcceptDone: notification.Active = 1; break;					
				}
			}
		} // end Notification

		public TaskSensitivity Sensitivity
		{
			get
			{ 
				switch(sensitivity.Active)
				{
					case 1: return TaskSensitivity.Personal;
					case 2: return TaskSensitivity.Private;
					case 3: return TaskSensitivity.Confidential;
					default: return TaskSensitivity.Public;
				}
			}
			set 
			{
				switch(value)
				{
					case TaskSensitivity.Public: sensitivity.Active = 0; break;
					case TaskSensitivity.Personal: sensitivity.Active = 1; break;
					case TaskSensitivity.Private: sensitivity.Active = 2; break;
					case TaskSensitivity.Confidential: sensitivity.Active = 3; break;
				}
			}
		} // end TaskSensitivity

		public TaskPriority Priority
		{
			get 
			{ 
				switch(priority.Active)
				{
					case 0: return TaskPriority.VeryHigh;
					case 1: return TaskPriority.High;
					case 3: return TaskPriority.Low;
					case 4: return TaskPriority.VeryLow;
					default: return TaskPriority.Average;
				}
			}
			set 
			{ 
				switch(value)
				{
					case TaskPriority.VeryHigh: priority.Active = 0; break;
					case TaskPriority.High: priority.Active = 1; break;
					case TaskPriority.Average: priority.Active = 2; break;
					case TaskPriority.Low: priority.Active = 3; break;
					case TaskPriority.VeryLow: priority.Active = 4; break;
				}
			}
		} // end Priority
		
		public int Percentage
		{
			get { return percentage.Active * 10; }
			set { percentage.Active = ( value / 10); }
		} // end Percentage
  }
}
